home *** CD-ROM | disk | FTP | other *** search
- /*
- * A very simple 16-bit TSR (POP-UP) calculator, featuring automatic entry
- * of last result into DOS applications. This feature works only on AT or
- * higher class machines with a recent BIOS.
- *
- * Use 'calc' with no operands for NON-TSR operation.
- *
- * If HOTKEYS are specified on the command line, CALC will install
- * itself as a TSR (Ram-Resident) program, which can be invoked at
- * any time by pressing the HOTKEYS. Available HOTKEYS are:
- * L - Left SHIFT
- * R - Right SHIFT
- * A - ALT
- * C - CONTROL
- * S - SysRq (Caution: some systems may not like this one)
- *
- * eg: CALC LR (Install with LEFT+RIGHT SHIFT for hotkeys)
- *
- * Keys used:
- * + Addition
- * - Subtraction
- * * Multiply
- * / Divide
- * % Modulus
- * & Bitwise AND
- * | Bitwise OR
- * ^ Bitwise EXCLUSIVE OR
- * < Shift left
- * > Shift right
- * = Display result
- * 0-9 Decimal input digits
- * A-F Hexidecimal input digits
- * 'c Enter a single ASCII character value
- * "cc Enter a dual ASCII character value
- * K Clear display
- * R Read value from memory
- * S Store value in memory
- * BKSP Clear last digit
- * SPACE Toggle HEX/DECIMAL
- * ESC Exit, no entry
- * ENTER Exit, enter value to DOS application (works only on AT or higher)
- * UP Move display up
- * DOWN Move display down
- * RIGHT Move display right
- * LEFT Move display left
- *
- * Copyright 1990-1994 Dave Dunfield
- * All rights reserved.
- *
- * Permission granted for personal (non-commercial) use only.
- *
- * Compile command: cc calc -fop
- */
- #include <stdio.h>
- #include <window.h>
- #include <tsr.h>
-
- int x=33, y=10, acc = 0, acc1, memory = 0;
- char op, mode = 0;
-
- /* Scan codes for entered digit values */
- char scans[] = {
- 0x0B, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0A, 0x1E, 0x30, 0x2E, 0x20, 0x12, 0x21 };
-
- /*
- * Main calculator program
- */
- calc()
- {
- char c, buffer[7];
-
- op = acc ? '=' : ' '; /* Use '=' reset mode if value left over */
-
- redraw:
- wopen(x, y, 9, 4, (WSAVE|WBOX2|WCOPEN|WSCROLL)+REVERSE);
- wcursor_off();
- for(;;) {
- wprintf(mode ? "\r%c $%04x" : "\r%c%6d", op, acc);
- switch(c = toupper(wgetc())) {
- case '+' : /* Record all operators */
- case '-' :
- case '*' :
- case '/' :
- case '%' :
- case '&' :
- case '|' :
- case '^' :
- case '<' :
- case '>' :
- doeval();
- wprintf(mode ? "\r $%04x\n" : "\r %6d\n", acc1);
- acc = 0;
- op = c;
- break;
- case '=' : /* Display partial result */
- doeval();
- wclwin();
- acc = acc1;
- op = '=';
- break;
- case '\'' : /* Single ASCII character */
- acc = wgetc();
- break;
- case '"' : /* Double ASCII character */
- acc = (wgetc() << 8) | wgetc();
- break;
- case _KBS : /* Delete last entered digit */
- acc /= mode ? 16 : 10;
- break;
- case _KUA : /* Move display up */
- if(y) --y;
- goto move;
- case _KDA : /* Move display down */
- if(y < 21) ++y;
- goto move;
- case _KLA : /* Move display left */
- if(x) --x;
- goto move;
- case _KRA : /* Move display right */
- if(x < 71)
- ++x;
- move:
- wclose();
- goto redraw;
- case ' ' : /* Toggle hex/decmal mode */
- mode = !mode;
- break;
- case '\n' : /* Exit and enter value */
- doeval();
- sprintf(buffer, mode ? "%x" : "%d", acc = acc1);
- for(acc1 = 0; c = buffer[acc1]; ++acc1)
- pushkey(c, scans[c]);
- wclose();
- return;
- case '\x1B' : /* Exit and don't enter value */
- doeval();
- acc = acc1;
- wclose();
- return;
- case 'K' : /* Clear the calculator display */
- acc = acc1 = 0;
- op = ' ';
- break;
- case 'S' : /* Save to memory */
- memory = acc;
- break;
- case 'R' : /* Restore from memory */
- acc = memory;
- break;
- default:
- if(op == '=') { /* Previous result to clear */
- acc = acc1 = 0;
- op = ' '; }
- if(mode) { /* Hex input */
- if(isdigit(c))
- acc = (acc * 16) + (c - '0');
- else if((c >= 'A') && (c <= 'F'))
- acc = (acc * 16) + (c - ('A'-10)); }
- else if(isdigit(c)) /* Decimal input */
- acc = (acc * 10) + (c - '0'); } }
- }
-
- /*
- * Evaluate the last recorded operation
- */
- doeval()
- {
- switch(op) {
- case '+' : acc1 += acc; break;
- case '-' : acc1 -= acc; break;
- case '*' : acc1 *= acc; break;
- case '/' : if(!acc) goto dbz; acc1 /= acc; break;
- case '%' : if(!acc) goto dbz; acc1 %= acc; break;
- case '&' : acc1 &= acc; break;
- case '|' : acc1 |= acc; break;
- case '^' : acc1 ^= acc; break;
- case '<' : acc1 <<=acc; break;
- case '>' : acc1 >>=acc; break;
- default : acc1 = acc; break;
- dbz: wprintf("\n? / 0\nError"); wgetc(); }
- }
-
- /*
- * Shove a key (char & scancode) into the BIOS keyboard buffer
- */
- pushkey(c, s) asm
- {
- MOV CH,4[BP] ; Get Scan code
- MOV CL,6[BP] ; Get character
- MOV AH,05h ; Push key...
- INT 16h ; Ask BIOS
- }
-
- /*
- * Main program, either TSR or execute main tty program menu
- */
- main(argc, argv)
- int argc;
- int *argv[];
- {
- int hot_keys;
- char *ptr;
-
- /* If RAM-resident, print startup message & TSR */
- if(argc > 1) {
- fputs("POP-UP Calculator\n\nCopyright 1990-1994 Dave Dunfield\nAll rights reserved.", stderr);
- hot_keys = 0;
- ptr = argv[1];
- while(*ptr) switch(toupper(*ptr++)) {
- case 'A' : hot_keys |= ALT; break;
- case 'C' : hot_keys |= CONTROL; break;
- case 'L' : hot_keys |= L_SHIFT; break;
- case 'R' : hot_keys |= R_SHIFT; break;
- case 'S' : hot_keys |= SYS_REQ; break;
- default: abort("\n\nInvalid HOTKEY"); }
- tsr(&calc, hot_keys, 2000); }
-
- /* Not RAM-resident, execute the program */
- calc();
- }
-